/*jslint vars: true, forin: true */
/*global angular: false, engine: false*/
engine.factory("EventStep", function (Step, config, Condition) {
	'use strict';
	/**
	 * EventStep extend from Step. This kind of Step will run after the
	 * condition is true. In addition, it can be setted a timeout time.
	 *
	 * @class EventStep
	 * @extends Step
	 * @constructor
	 */

	var EventStep = function EventStep(options) {
		this.salt = (/[0-9a-f]{6}/).gen;
		/**
		 * Execute the step when the condition is true.
		 * @property condition
		 * @type condition
		 * @default null
		 */
		this.condition = new Condition(options.condition);

		/**
		 * If the condition can't be true in timeout time,
		 * throw a timeout message.
		 *
		 * @property overtime
		 * @type number
		 * @default EVENT_TIMEOUT
		 */
		this.overtime = options.overtime || 10000;

		Step.call(this, options);
	};
	EventStep.prototype = new Step();
	EventStep.prototype.constructor = EventStep;
	/**
	 * EventStep default runing function.
	 * @method run
	 * @returns status {number}
	 */
	EventStep.prototype.run = function () { // Condition checking overtime timer.
		var that = this;
		var start_time = (new Date()).getTime();

		var timeout_id = setTimeout(
			function () {
				clearInterval(interval_id);
				that.$process.doException();
			}, 10000
			/* config.get("EVENT_TIMEOUT")*/
		);
		// According to the designated interval to check the occurrence of the event.
		var interval_id = setInterval(
			function () {
				if (that.condition.test() && that.$run()) {
					that.$process.result.addTime(that.$timing(start_time), that.salt);
					// When the event occurs, cancel the Interval
					// timer and Timeout timer.
					clearInterval(interval_id);
					clearTimeout(timeout_id);

					that.$process.$core();
				}
			}, 50
			/*config.get("EVENT_TEST_CYCLE") */
		);
	};
	/**
	 * The timing and write results to Process.
	 * @method $timing
	 */
	EventStep.prototype.$timing = function ($start_time) {
		return (new Date()).getTime() - $start_time;
	};

	EventStep.prototype.toOptions = function () {
		var options = {};
		angular.forEach(Step.prototype.toOptions.call(this), function (value, key) {
			this[key] = value;
		}, options);
		options.overtime = this.overtime;
		options.type = "EventStep";
		options.condition = this.condition.toString;

		return options;
	};

	EventStep.prototype.toJson = function () {
		var json = Step.prototype.toJson.call(this);
		json.type = "EventStep";
		json.typeparam = angular.toJson({
			condition: this.condition.toString(),
			overtime: 10000
		});

		return json;
	};

	return EventStep;
});
